package it.uniroma2.art.coda.structures.table;

import it.uniroma2.art.coda.pearl.model.BindingStruct;
import it.uniroma2.art.coda.pearl.model.PlaceholderStruct;
import it.uniroma2.art.owlart.model.ARTNode;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class TablePlaceholdersBindingsVariables {

	private List <Map<String, SingleTableValue>>placeholderBindingList;
	private List <Map<String, SingleTableValue>>placeholderBindingVariablesList;
	
	public TablePlaceholdersBindingsVariables(){
		placeholderBindingList = new ArrayList<Map<String,SingleTableValue>>();
		placeholderBindingVariablesList = new ArrayList<Map<String,SingleTableValue>>();
	}
	
	public void constructPlaceholderBindingMap(List <List<ValueForTable>> valueForTableList){
		
		recursiveFirstMapConstruct(valueForTableList, 0, new HashMap<String, SingleTableValue>());
	}
	
	private void recursiveFirstMapConstruct(List <List<ValueForTable>> valueForTableListList,
			int index, Map<String, SingleTableValue> idToSingleTableValueMap){
		
		
		List<ValueForTable> valueForTableList = valueForTableListList.get(index);
		
		for(ValueForTable valueForTable : valueForTableList){
			//First of all clone the input map and word on this clone
			Map<String, SingleTableValue> idToSingleTableValueClonedMap = 
					new HashMap<String, SingleTableValue>();
			for(String key : idToSingleTableValueMap.keySet())
				idToSingleTableValueClonedMap.put(key, idToSingleTableValueMap.get(key));
			
			//Depenending of the type of currentElement perform a different action
			if(valueForTable instanceof ValueForTablePlaceholder){
				ValueForTablePlaceholder currentElementPlaceholder = 
						(ValueForTablePlaceholder) valueForTable;
				String id = currentElementPlaceholder.getId();
				ARTNode artNode = currentElementPlaceholder.getArtNode();
				PlaceholderStruct placeholderStruct = currentElementPlaceholder.getPlaceholderStruct();
				SingleTableValuePlaceholder singleTableValuePlaceholder = 
						new SingleTableValuePlaceholder(id, artNode, placeholderStruct);
				idToSingleTableValueClonedMap.put(id, singleTableValuePlaceholder);
			} else if(valueForTable instanceof ValueForTableBinding){
				ValueForTableBinding currentElementBinding = (ValueForTableBinding) valueForTable;
				BindingStruct bindingStruct = currentElementBinding.getBindingStruct();
				Map <String, ARTNode>idToARTNodeMap = currentElementBinding.getIdToARTNodeMap();
				for(String bindId : idToARTNodeMap.keySet()){
					idToARTNodeMap.get(bindId);
					ARTNode artNode = idToARTNodeMap.get(bindId);
					SingleTableValueBinding singleTableValueBinding = 
							new SingleTableValueBinding(bindId, artNode, bindingStruct);
					idToSingleTableValueClonedMap.put(bindId, singleTableValueBinding);
				}
			}
			
			if(valueForTableListList.size() == index+1){
				//this is the last element of the valueForTableList, so store the idToSingleTableValueClonedMap
				placeholderBindingList.add(idToSingleTableValueClonedMap);
			} else{
				recursiveFirstMapConstruct(valueForTableListList, index+1, idToSingleTableValueClonedMap);
			}
		}
		
	}
	
	public void addVariableValueToPlaceholderBindingVariableMap(
			Collection<SingleTableValue> singleTableValuePlaceholderBindingList, 
			List<List<SingleTableValueVariable>> valueVariableList){

		Map<String, SingleTableValue> idToSingleTableValueMap = new HashMap<String, SingleTableValue>();
		//first of all add to the map the value corresponding to the placeholder and the binding
		for(SingleTableValue singleTableValue : singleTableValuePlaceholderBindingList){
			idToSingleTableValueMap.put(singleTableValue.getId(), singleTableValue);
		}
		
		if(valueVariableList == null || valueVariableList.isEmpty()){
			placeholderBindingVariablesList.add(idToSingleTableValueMap);
		} else{
			//now add the variable associated values
			recursiveSecondMapConstruct(valueVariableList, 0, idToSingleTableValueMap);
		}
	}
	
	private void recursiveSecondMapConstruct(
			List<List<SingleTableValueVariable>> valueVariableList, int index, 
			Map<String, SingleTableValue> idToSingleTableValueMap){
		
		List<SingleTableValueVariable> currentElementList = valueVariableList.get(index);
		
		for(SingleTableValueVariable singleTableVariable : currentElementList){
			//First of all clone the input map and word on this clone
			Map<String, SingleTableValue> idToSingleTableValueClonedMap = 
					new HashMap<String, SingleTableValue>();
			for(String key : idToSingleTableValueMap.keySet())
				idToSingleTableValueClonedMap.put(key, idToSingleTableValueMap.get(key));
			
			idToSingleTableValueClonedMap.put(singleTableVariable.getId(), singleTableVariable);
			
			if(valueVariableList.size() == index+1){
				//this is the last element of the valueForTableList, so store the idToSingleTableValueClonedMap
				placeholderBindingVariablesList.add(idToSingleTableValueClonedMap);
			} else{
				recursiveSecondMapConstruct(valueVariableList, index+1, idToSingleTableValueClonedMap);
			}
		}		
	}

	
	public Iterator<Map<String, SingleTableValue>> getIteratorForPlaceholderBindingMap(){
		return placeholderBindingList.iterator();
	}
	
	
	public Iterator<Map<String, SingleTableValue>> getIteratorForPlaceholderBindingVariableMap(){
		return placeholderBindingVariablesList.iterator();
	}
	
	public void printPlaceholderBindingTable(){
		boolean firstRow = true;
		for(Map<String, SingleTableValue> row : placeholderBindingList){
			if(firstRow){
				firstRow = false;
				for(String id : row.keySet()){
					System.out.print("\t\t"+id+"\t\t||");
				}
				System.out.println();
			}
			System.out.println();
			for(String id : row.keySet()){
				System.out.print(row.get(id).toString() + " || ");
			}
			
		}
	}
	
	
	public void printPlaceholderBindingVariableTable(){
		for(Map<String, SingleTableValue> row : placeholderBindingVariablesList){
			boolean firstRow = true;
			if(firstRow){
				firstRow = false;
				for(String id : row.keySet()){
					System.out.print(id+"\t\t");
				}
				System.out.println();
			}
			System.out.println();
			for(String id : row.keySet()){
				System.out.print(row.get(id).toString() + " || ");
			}
		}
	}
}
